package org.duang.token;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.duang.common.exceptios.ServiceException;
import org.duang.config.Config;
import org.duang.core.Controller;
import org.duang.kit.ToolsKit;

/**
 * TokenManager.
 */
public class TokenManager {
	
	private static ITokenCache tokenCache;
	private static SecureRandom random = new SecureRandom();
	
	private TokenManager() {
		
	}
	
	public static void init(ITokenCache tokenCache) {
		if (tokenCache == null)
			return;
		
		TokenManager.tokenCache = tokenCache;
		
		long halfTimeOut = Config.getTokenTimeOut() * 1000 / 2;	// Token最小过期时间的一半时间作为任务运行的间隔时间
		new Timer().schedule(new TimerTask() {public void run() {removeTimeOutToken();}},
							 halfTimeOut,
							 halfTimeOut);
	}
	
	/**
	 * 创建Token.
	 */
	public static void createToken(Controller controller, String tokenName, int secondsOfTimeOut) {
		if (ToolsKit.isEmpty(tokenCache)) {
			throw new ServiceException("tokenplugin is stop.... Please start it.");
		}
		else {
			createTokenUseTokenIdGenerator(controller, tokenName, secondsOfTimeOut);
		}
	}
	
	/**
	 * 在页面中使用 ${token} 显示
	 */
	private static void createTokenHiddenField(Controller controller, String tokenName, String tokenId) {
		StringBuilder sb = new StringBuilder();
		sb.append("<input type='hidden' id='").append(tokenName).append("_id' name='").append(tokenName).append("' value='" + tokenId).append("' />");
		controller.setValue("token", sb.toString());
	}
	
	private static void createTokenUseTokenIdGenerator(Controller controller, String tokenName, int secondsOfTimeOut) {
		if (secondsOfTimeOut < Config.getTokenTimeOut())
			secondsOfTimeOut = (int)Config.getTokenTimeOut();
		
		String tokenId = null;
		Token token = null;
		int safeCounter = 3;
		do {
			if (safeCounter-- == 0)
				throw new RuntimeException("Can not create tokenId.");
			tokenId = String.valueOf(random.nextLong());
			token = new Token(tokenId, System.currentTimeMillis() + (secondsOfTimeOut * 1000));
		} while(ToolsKit.isEmpty(tokenId)|| tokenCache.contains(token));
		
		controller.setValue(tokenName, tokenId);
		tokenCache.put(token);
		createTokenHiddenField(controller, tokenName, tokenId);
	}
	
	/**
	 * 验证Token
	 */
	public static synchronized boolean validateToken(Controller controller, String tokenName) {
		String clientTokenId = controller.getValue(tokenName);
		if (ToolsKit.isEmpty(tokenCache)) {
			throw new ServiceException("tokenplugin is stop.... Please start it.");
		}
		else {
			Token token = new Token(clientTokenId);
			boolean result = tokenCache.contains(token); 
			tokenCache.remove(token);
			return result;
		}
	}
	
	/**
	 * 删除过期Token
	 */
	private static void removeTimeOutToken() {
		List<Token> tokenInCache = tokenCache.getAll();
		if (ToolsKit.isEmpty(tokenCache)) 
			return;
		
		List<Token> timeOutTokens = new ArrayList<Token>();
		long currentTime = System.currentTimeMillis();
		for (Token token : tokenInCache)
			if (token.getExpirationTime() <=  currentTime)
				timeOutTokens.add(token);
		
		for (Token token : timeOutTokens)
			tokenCache.remove(token);
	}
	
	public static void removeAllToken(){
		List<Token> tokenInCache = tokenCache.getAll();
		if (ToolsKit.isEmpty(tokenCache)) 
			return;
		tokenInCache.clear();
		tokenInCache = null;
	}
}





